#!/usr/bin/env python3

"""Convenience entrypoint to run the full analytics pipeline in one command."""

from __future__ import annotations

import argparse
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).parent.resolve()
SCRIPTS_DIR = ROOT / "analysis_scripts"


def _derived_path(path: Path, suffix: str) -> Path:
    return path.with_name(f"{path.stem}{suffix}{path.suffix}")


def _run_step(step: str, command: list[str]) -> None:
    print(f"[{step}] {' '.join(command)}")
    subprocess.run(command, check=True)


def orchestrate_pipeline(
    input_path: Path,
    output_dir: Path,
    encoding: str,
    top_posts: int,
    time_column: str,
    group_mode: str,
) -> None:
    if not input_path.exists():
        raise SystemExit(f"Input CSV not found: {input_path}")
    output_dir.mkdir(parents=True, exist_ok=True)

    prepare_script = SCRIPTS_DIR / "prepare_dataset.py"
    lifecycle_script = SCRIPTS_DIR / "derive_cycle_phrase.py"
    metrics_script = SCRIPTS_DIR / "build_metrics.py"
    for script in (prepare_script, lifecycle_script, metrics_script):
        if not script.exists():
            raise SystemExit(f"Required script missing: {script}")

    cleaned_path = _derived_path(input_path, "_clean")
    lifecycle_path = _derived_path(cleaned_path, "_with_cycle")

    _run_step(
        "1/3 prepare_dataset",
        [
            sys.executable,
            str(prepare_script),
            "--input",
            str(input_path),
            "--encoding",
            encoding,
        ],
    )

    _run_step(
        "2/3 derive_cycle_phrase",
        [
            sys.executable,
            str(lifecycle_script),
            "--input",
            str(cleaned_path),
            "--encoding",
            encoding,
            "--lifecycle-column",
            "cycle_phrase",
        ],
    )

    build_command = [
        sys.executable,
        str(metrics_script),
        "--input",
        str(lifecycle_path),
        "--output-dir",
        str(output_dir),
        "--top-posts",
        str(top_posts),
        "--group-mode",
        group_mode,
    ]
    if time_column:
        build_command.extend(["--time-column", time_column])

    _run_step("3/3 build_metrics", build_command)


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="Run prepare -> lifecycle -> metrics pipeline in sequence."
    )
    parser.add_argument(
        "input",
        type=str,
        help="Path to the source CSV file (raw or cleaned).",
    )
    parser.add_argument(
        "--encoding",
        default="gb18030",
        help="CSV encoding for all read/write operations (default: gb18030).",
    )
    parser.add_argument(
        "--output-dir",
        default=str(ROOT / "analysis_data"),
        help="Directory to store generated artifacts (default: analysis_data).",
    )
    parser.add_argument(
        "--top-posts",
        type=int,
        default=10,
        help="Number of representative posts per phase (default: 10).",
    )
    parser.add_argument(
        "--time-column",
        default="time",
        help="Preferred time column name for build_metrics (default: time).",
    )
    parser.add_argument(
        "--group-mode",
        choices=("lifecycle-stance-bend", "lifecycle-bend"),
        default="lifecycle-stance-bend",
        help=(
            "Choose 'lifecycle-stance-bend' (default) to keep stance dimension in lifecycle/BEND "
            "outputs or 'lifecycle-bend' to aggregate by lifecycle and BEND only."
        ),
    )
    return parser.parse_args()


def main() -> None:
    args = parse_args()
    orchestrate_pipeline(
        input_path=Path(args.input).resolve(),
        output_dir=Path(args.output_dir).resolve(),
        encoding=args.encoding,
        top_posts=args.top_posts,
        time_column=args.time_column,
        group_mode=args.group_mode,
    )


if __name__ == "__main__":
    try:
        main()
    except subprocess.CalledProcessError as exc:
        raise SystemExit(
            f"Pipeline step failed with exit code {exc.returncode}. "
            f"Command: {' '.join(exc.cmd)}"
        ) from exc
